import { notification } from "antd";
import { stringify } from "querystring";
import { useCallback } from "react";
import { useRecoilState } from "recoil";

import { userState } from "./../stores/user";

const apiUrl = import.meta.env.VITE_BASE_URL;

interface Config extends RequestInit {
  data?: any;
  json?: boolean;
  token?: string;
}

/**公共的 HTTP 请求封装 */
export const request = <T>(
  endpoint: string,
  { data, token, json, method, ...customConfig }: Config = {}
) => {
  const config = {
    method: method ? method : "GET",
    headers: {
      token: token ? token : "",
      "Content-type": json
        ? "application/json"
        : "application/x-www-form-urlencoded",
    },
    ...customConfig,
  };

  if (
    config.method.toUpperCase() === "GET" ||
    config.method.toUpperCase() === "DELETE"
  ) {
    endpoint += `?${stringify(data)}`;
  } else {
    if (json) {
      config.body = JSON.stringify(data);
    } else {
      config.body = stringify(data);
    }
  }

  return window
    .fetch(`${apiUrl}${endpoint}`, config)
    .then(async (response) => {
      if (response.status === 401) {
        // await auth.logout();
      }
      const data = await response.json();
      if (data.code === 500) {
        notification.error({
          message: data.message,
        });
        return Promise.reject({ message: data.message });
      }
      if (data.code === 401) {
        // await auth.logout();
        // window.location.href = "/login";
        return Promise.reject({ message: "请重新登录" });
      }
      if (data.code === 200) {
        if (data.message && data.message.length > 0) {
          notification.success({
            message: data.message,
          });
        }
        return Promise.resolve(data.data as T);
      }
      return Promise.reject({ ...data, msg: data.data });
    })
    .catch((e) => {
      return Promise.reject(e);
    });
};

export const useRequest = <T>() => {
  const [user] = useRecoilState(userState);
  return useCallback(
    (...[endpoint, config]: Parameters<typeof request>) =>
      request<T>(endpoint, { ...config, token: user?.token || "" }),
    [user?.token]
  );
};
